from __future__ import print_function ## a hack to enable print as a function. This MUST come as the first line.
import sys
import logging
import puzautils.table.puza_memory_table as pmt
import puzautils.twitter_api.twitter_crawler as tc
from multiprocessing import Process, Value, Lock
import time
import math


seed_table_name = sys.argv[1]
save_table_name = sys.argv[2]
log_filename = sys.argv[3]

def detect_dead(ft, lock):
    global last_time
    flag = 0
    with lock:        
        diff = math.fabs(ft.value - time.time())
        if math.floor(diff) > 180:
            logging.warn('Crawling process hangs. [Timeout]:' + str(diff))
            flag = 1
    return flag

if __name__ == '__main__':
    logging.basicConfig(filename= log_filename, filemode='w', level=logging.INFO, format='%(asctime)s::%(levelname)s::[%(module)s::%(funcName)s]::%(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
    c = tc.TwitterCrawler('day')
    c.Auth()
    c.PlainTextFile = save_table_name
    ## read seeds
    logging.info("Start to load seed table.")
    SeedTable = pmt.PuzaMemoryTable()
    SeedTable.InputFile(seed_table_name)
    SeedTable.Load()
    logging.info("Finish to load seed table.")
    logging.info("Total:" + str(len(SeedTable)))
    ## finish seeds
    for i in range(len(SeedTable)):
        user_id = ''
        sn = ''
        if SeedTable[i]['id'] != None:
            user_id = SeedTable[i]['id']
        else:
            sn = SeedTable[i]['screenname']
        logging.info('Start to handle user:'+str(user_id))
        fail = 0
        success = 0
        while True:
            get_lock = 0
            r = tc.CrawlerReporter()
            while get_lock == 0:
                try:                
                    ft = Value('d',time.time())
                    lock = Lock()
                    get_lock = 1
                except:
                    logging.info('Fail to get locked value and wait 5 seconds.')
                    time.sleep(5)
            r.SetReport(ft, lock)                
            c.Reporter =r
            t = Process(target=c.GetUserAllTimeline, args=(sn, user_id, -1, None))
            logging.info('Crawling process is started. [Start]:' + str(fail))                
            t.start()
            while True:
                if t.is_alive():
                    time.sleep(0.1)
                    if detect_dead(ft, lock) == 1:
                        fail = fail + 1
                        logging.info('Crawling process is terminated. [Terminated]:' + str(fail))
                        time.sleep(30)
                        logging.info('Wait 30 seconds to another trial.' + str(fail))
                        break
                else:
                    success = 1
                if success == 1:
                    logging.info('Crawling process is completed. [Completed]:' + str(fail))
                    t.terminate()
                    break
            if success == 1:
                break             
            if fail > 3:
                break                
        logging.info('Finish to handle user:'+str(user_id))
        time.sleep(1)
    logging.info('Finished.')